package com.scott.proxy.lesson01.proxy;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import com.scott.proxy.lesson01.entity.TimeProxy;
import com.scott.proxy.lesson01.service.Moveable;

public class Proxy {

	public static Object newProxyInstance(Class<?> interfaces,TimeProxy handler) throws Exception{
		
		
		String clzName="$Proxy1";
		
		String rn="\r\n";
		Method[] methods = interfaces.getMethods();
		String methodStr="";
		
		/*for(Method method: methods){
			String name =method.getName();
			methodStr += methodStr + "\t@Override"+rn
					+"\tpublic void "+name+"(){"+rn+
										"\t\tlong begin = System.currentTimeMillis();"+rn+
										"\t\tSystem.out.println(\"开始时间=[\"+begin+\"]\");"+rn+
										"\t\tt."+name+"();"+rn+
										"\t\tlong end = System.currentTimeMillis();"+rn+
										"\t\tSystem.out.println(\"结束时间=[\"+end+\"]\");"+rn+
										"\t\tSystem.out.println(\"方法的运行时间：[\"+ (end -begin)+\"]毫秒...\");"+rn+
									"\t}";
		}*/
		
		for(Method method: methods){
			String name =method.getName();
			methodStr += methodStr + "\t@Override"+rn
					+"\tpublic void "+name+"(){"+rn+
										"\t\ttry {"+rn+
										"\t\t\tMethod md ="+ interfaces.getName()+".class.getMethod(\""+name+"\");"+rn+
										"\t\t\t"+"handler.invoke(this,md);"+rn+
										"\t\t} catch (Exception e) {"+rn+
											"\t\t\te.printStackTrace();"+rn+
										"\t\t}" +rn+
									"\t}";
		}
		
		String src=
		"package com.scott.proxy.lesson02.service.impl;"+rn+
		
		"import java.lang.reflect.Method;"+rn+
		"import com.scott.proxy.lesson01.proxy.InvocationHandler;"+rn+
		"import com.scott.proxy.lesson01.service.Moveable;"+rn+

		"public class "+clzName+" implements "+interfaces.getName()+" {"+rn+
			
			"\tprivate InvocationHandler handler;"+rn+rn+
			"\tpublic "+clzName+"(InvocationHandler handler){"+rn+
				"\t\tthis.handler =handler;"+rn+
			"\t}"+rn+rn+
			
			
			methodStr+rn+

		"}";	
		
		String root=System.getProperty("user.dir");
		System.out.println(root);
		String dir = "d:/src/main/java/com/scott/proxy/lesson02/service/impl/";
		String fileName=dir+clzName+".java";
		
		//根据目录生成1个文件
		File f =new File(fileName);
		
		//把src写到文件中
		FileWriter fw = new FileWriter(f);
		
		//写的内容
		fw.write(src);
		fw.flush();
		fw.close();
		
		//把.java文件变成.class文件
		compile(f);
		
		
		//加载到内存并生成1个对象   加载： 把硬盘上的java文件放到内存中来  不管
		URL[] urls = new URL[]{new URL("file:/"+"d:/src/main/java/")};
		URLClassLoader loader = new URLClassLoader(urls);
		Class<?>  clz = loader.loadClass("com.scott.proxy.lesson02.service.impl."+clzName);
		System.out.println(clz);
		loader.close();
		
		//利用构造方法的反射生成类的对象
		Constructor<?> constructor = clz.getConstructor(InvocationHandler.class);
		//Tank 被代理对象   Moveable代理对象
		Object m = (Moveable) constructor.newInstance(handler);
		return  m;
	}
	
	private static void compile(File f) throws IOException {
		//JDK6才提供的类  拿到系统默认的java编译器 javac
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		System.out.println(compiler.getClass().getName());
		StandardJavaFileManager fileManager =compiler.getStandardFileManager(null, null, null);
		Iterable<? extends JavaFileObject> units = fileManager.getJavaFileObjects(f);
		
		//编译任务
		CompilationTask task=compiler.getTask(null, fileManager, null, null, null, units);
		//执行编译
		task.call();
		fileManager.close();
	}
}
